package com.wuyb.aop;

import com.alibaba.fastjson2.JSONObject;
import com.wuyb.pojo.entity.BaseResponse;
import com.wuyb.pojo.param.UserAddParam;
import com.wuyb.service.AdminLogService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.DefaultParameterNameDiscoverer;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

/**
 * Created with IntelliJ IDEA.
 *
 * @Author: wyb
 * @Date: 2024/01/07/19:04
 * @Description:
 */
@Aspect
@Component
@Slf4j
public class OperationLogAspect {

    @Resource
    private AdminLogService adminLogService;



    @Pointcut("@annotation(com.wuyb.aop.OperationLogAnnotation)")
    public void operLogPoincut() {}


    @AfterReturning(returning = "result", value = "operLogPoincut()")
    public void saveOperLog(JoinPoint joinPoint, BaseResponse result) {
        // 从切面织入点处通过反射机制获取织入点处的方法
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //获取切入点所在的方法
        Method method = signature.getMethod();

        // 获取注解信息
        OperationLogAnnotation annotation = method.getAnnotation(OperationLogAnnotation.class);
        if (annotation != null) {
            // 获取参数值
            Object[] args = joinPoint.getArgs();
            // 获取参数类型
            Class<?>[] parameterTypes = method.getParameterTypes();

            // 获取参数名
            String[] parameterNames = new DefaultParameterNameDiscoverer().getParameterNames(method);

            // 建立上下文字典，储存参数信息
            StandardEvaluationContext standardEvaluationContext = new StandardEvaluationContext();
            for (int i = 0; i < args.length; i++) {
                if (parameterNames[i] != null) {
                    // JSONObject.toString 可以将对象转换为json字符串
                    Object parameterArg = args[i];

                    // 判断该类是否为UserAddParam， 则清空密码
                    if (UserAddParam.class == parameterTypes[i]) {
                        ((UserAddParam) parameterArg).setPassword(null);
                    }

                    try {
                        standardEvaluationContext.setVariable(parameterNames[i], JSONObject.toJSONString(parameterArg));
                    } catch (Exception e) {
                        log.warn(String.format("%s(): %s 参数转换json失败", method.getName(), parameterArg));
                    }
                }
            }

            // 使用Spel表达式替换文本
            SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
            // 替换URL
            Expression expression = spelExpressionParser.parseExpression(annotation.actionUrl(), ParserContext.TEMPLATE_EXPRESSION);
            // 替换Content
            Expression expression1 = spelExpressionParser.parseExpression(annotation.actionContent(), ParserContext.TEMPLATE_EXPRESSION);

            adminLogService.insert(
                    annotation.actionModule(),
                    annotation.actionType(),
                    (String) expression.getValue(standardEvaluationContext),
                    (String) expression1.getValue(standardEvaluationContext),
                    result.getCode() == 200
            );
        }
    }
}
